package jwcb.javapjframework.common.redis.RedisService.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import jwcb.javapjframework.common.domain.constants.CommonConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Configuration
public class RedisConfig {

    private static final Logger log = LoggerFactory.getLogger(RedisConfig.class);

    /**
     * 配置RedisTemplate并定义序列化规则
     *
     * @param redisConnectionFactory redis连接工厂（由Spring Boot自动注入）
     * @return 自定义序列化规则的Redis操作模板
     *
     * 关键配置说明：
     * 1. setKeySerializer/setHashKeySerializer:
     *    - 使用StringRedisSerializer序列化String类型的键和Hash的字段名
     *    - 确保键可读且兼容所有Redis命令
     * 2. setValueSerializer:
     *    - 值使用GenericJackson2JsonRedisSerializer进行JSON序列化
     *    - 支持复杂对象存储并保留类型信息
     * 3. setHashValueSerializer:
     *    - Hash类型的值同样使用JSON序列化器
     * 4. afterPropertiesSet():
     *    - 初始化模板确保配置生效
     *
     *
     */
    @Bean(name = "customRedisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("Configure Redis serialization");
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer =
                createJacksonSerializer();
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }


    /**
     * 创建自定义Jackson序列化器
     *
     * @return 配置了安全策略的JSON序列化器
     *
     * ObjectMapper关键配置详解：
     * 1. FAIL_ON_UNKNOWN_PROPERTIES(false):
     *    - 反序列化时忽略JSON中的未知字段，增强兼容性
     * 2. WRITE_DATES_AS_TIMESTAMPS(false):
     *    - 禁用日期转时间戳，使用格式化字符串输出日期
     * 3. FAIL_ON_EMPTY_BEANS(false):
     *    - 允许序列化空Bean对象而不抛异常
     * 4. FAIL_ON_INVALID_SUBTYPE(false):
     *    - 忽略无效子类型错误，提高容错性
     * 5. WRITE_DATE_KEYS_AS_TIMESTAMPS(false):
     *    - Map中的日期键也使用格式化字符串
     * 6. defaultDateFormat():
     *    - 统一日期格式为"yyyy-MM-dd HH:mm:ss"标准格式
     * 7. USE_ANNOTATIONS(false):
     *    - 禁用Jackson注解处理（根据需求可选）
     * 8. JavaTimeModule():
     *    - 注册Java8时间模块（LocalDateTime等支持）
     * 9. serializationInclusion(NON_NULL):
     *    - 序列化时自动忽略null值字段
     */
    public GenericJackson2JsonRedisSerializer createJacksonSerializer() {
        // 创建自定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT);

        // 创建并配置 JavaTimeModule
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));

        ObjectMapper objectMapper =
                JsonMapper.builder()
                        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                        .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
                        .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
                        .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
                        .defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
                        .configure(MapperFeature.USE_ANNOTATIONS, false)
                        // 注册自定义时间模块
                        .addModule(javaTimeModule)
                        .serializationInclusion(JsonInclude.Include.NON_NULL)
                        .build();

        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }
}
